﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Controls;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.IO;
using System.Windows.Forms;
using System.Drawing;
using DiasEngineDate.UI;

namespace DiasEngineDate
{
     public class DiasNetClientStdio
     {
         // 最大的窗体
         
         //引用配置文件库
         [DllImport("kernel32")]
         private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
         [DllImport("kernel32")]
         private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);

         //[成员函数]
         //图像函数
         private System.Drawing.Image _img;
         [StructLayout(LayoutKind.Sequential, Pack = 1)]

         internal struct TokPriv1Luid
         {

             public int Count;

             public long Luid;

             public int Attr;

         }

         //网络连接状态
         public bool netstat = false;

         [DllImport("kernel32.dll", ExactSpelling = true)]

         internal static extern IntPtr GetCurrentProcess();

         [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]

         internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);

         [DllImport("advapi32.dll", SetLastError = true)]

         internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);

         [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]

         internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,

         ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

         [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]

         internal static extern bool ExitWindowsEx(int flg, int rea);

         internal const int SE_PRIVILEGE_ENABLED = 0x00000002;

         internal const int TOKEN_QUERY = 0x00000008;

         internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;

         internal const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";

         internal const int EWX_LOGOFF = 0x00000000;  //注销

         internal const int EWX_SHUTDOWN = 0x00000001;   //关机

         internal const int EWX_REBOOT = 0x00000002;     //重启

         internal const int EWX_FORCE = 0x00000004;

         internal const int EWX_POWEROFF = 0x00000008;    //断开电源

         internal const int EWX_FORCEIFHUNG = 0x00000010;  //强制终止未响应的程序

         //主窗体文本控件用于展示服务器发送过来的信息
         System.Windows.Controls.TextBox textbox;


         //存储用户选择的菜单选项？
         public string ClientAction;

         private static void DoExitWin(int flg)
         {

             bool ok;

             TokPriv1Luid tp;

             IntPtr hproc = GetCurrentProcess();

             IntPtr htok = IntPtr.Zero;

             ok = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);

             tp.Count = 1;

             tp.Luid = 0;

             tp.Attr = SE_PRIVILEGE_ENABLED;

             ok = LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);

             ok = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);

             ok = ExitWindowsEx(flg, 0);

         }

         bool b = true;
         Socket sokClient = null;//负责与服务端通信的套接字
         Thread threadClient = null;//负责 监听 服务端发送来的消息的线程
         Thread connectstat = null;//负责监听与服务端的连接状态
         bool isRec = true; //是否循环接收服务端数据

         //启动连接网络服务器端
         public void StartConnectingServer(bool _netstat)
         {
             netstat = _netstat;
             //以客户端身份连接
             //Control.CheckForIllegalCrossThreadCalls = false;//关闭线程监视
             //和主机连接起来——————为了避免假死，就弄个线程过来
             Thread th = new Thread(new ThreadStart(ClientConnect));
             th.IsBackground = true;//[后台线程--主窗体被关闭了，程序会立刻结束]
             th.Start();
         }

         //连接服务器
         public void ClientConnect()
         {
             while (b)//连接没问题就只连接一次，一旦出现问题就反复连接直到成功
             {
                 try
                 {
                     //实例化 套接字
                     sokClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                     //创建 ip对象
                     //IPAddress address = IPAddress.Parse(Convert.ToString(Encryption_Decryption.Decrypt(IniReadValue("Server", "server", AppDomain.CurrentDomain.BaseDirectory + "\\Config.ini"))));
                     IPAddress address = IPAddress.Parse("127.0.0.1");
                     //MessageBox.Show("address");
                     //创建网络节点对象 包含 ip和port
                     IPEndPoint endpoint = new IPEndPoint(address, int.Parse("8885"));
                     //连接 服务端监听套接字
                     sokClient.Connect(endpoint);

                     b = false;
                     netstat = true;

                     //创建负责接收 服务端发送来数据的 线程
                     threadClient = new Thread(ReceiveMsg);
                     threadClient.IsBackground = true;  //这行是我注释的
                     //如果在win7下要通过 某个线程 来调用 文件选择框的代码，就需要设置如下
                     threadClient.SetApartmentState(ApartmentState.STA);
                     threadClient.Start();


                     //连接成功，发送用户名给服务端
                     byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes("--"+ DateTime.Now.ToString()+"\n--"+Login.Suser +"["+Login.SuserName+ "]正在连接到服务器...\n");
                     sokClient.Send(arrMsg);
                 }
                 catch
                 {
                     b = true;//有问题，那就继续连呗，反正又不是咱们的电脑，不能告诉他详细信息的
                     netstat = false;
                     //提示连接到服务器
                     Monitor.InFunction("--" + DateTime.Now.ToString() + "\n--连接服务器失败...\n");
                 }
             }
         }

         //接收服务端发送来的消息数据
         void ReceiveMsg()
         {
             while (isRec)
             {

                 byte[] msgArr = new byte[1024 * 1024 * 1];//接收到的消息的缓冲区
                 int length = 0;
                 //接收服务端发送来的消息数据
                 try
                 {
                     length = sokClient.Receive(msgArr);//Receive会阻断线程
                     if (msgArr[0] == 0)//发送来的是文字
                     {
                         if (length - 1 >= 0)
                         {
                             try
                             {
                                 string strMsg = System.Text.Encoding.UTF8.GetString(msgArr, 1, length - 1);
                                 //将信息显示到窗口
                                 Monitor.InFunction("--"+DateTime.Now.ToString()+"\n--服务器信息：" + strMsg+"\n");
                             }
                             catch (Exception)
                             {

                             }

                         }
                         //txtShow.AppendText(strMsg + "rn");
                     }
                     else if (msgArr[0] == 1)
                     {
                         //发送来的是文件
                         //string abc = Encoding.Default.GetString(msgArr);
                         //MessageBox.Show(abc);
                         SystemInformations ai = new SystemInformations("系统信息", "服务器向您发送一分文件？是否接收？");
                         ai.ShowDialog();
                         if (ai.TheResult == "OK")
                         {
                             SaveFileDialog sfd = new SaveFileDialog();
                             sfd.Filter = "文本文件(.txt)|*.txt|压缩文件(.rar)|*.rar|图片文件(*.JPG)|*.JPG|Excel文件(.xls)|*.xls|Word文件(.doc)|*.doc|所有文件(*.*)|*.*";
                             //弹出文件保存选择框
                             if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                             {
                                 //创建文件流
                                 using (FileStream fs = new FileStream(sfd.FileName, FileMode.OpenOrCreate))
                                 {
                                     fs.Write(msgArr, 1, length - 1);
                                     SystemInformations si = new SystemInformations("保存成功", "文件已经保存？");
                                     si.ShowDialog();
                                     //MessageBox.Show("文件保存成功！");
                                 }
                                 byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes("--" + DateTime.Now.ToString() +"\n"+ Login.SuserName + "已经接收文件.\n");
                                 sokClient.Send(arrMsg);
                             }
                         }
                         else
                         {
                             SystemInformations aie = new SystemInformations("接收错误", "您放弃接收服务器核心文件?");
                             aie.ShowDialog();
                             byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes("--" + DateTime.Now.ToString() +"\n"+ Login.SuserName + "可恶的拒绝了接收您发送的文件.\n");
                             sokClient.Send(arrMsg);
                             Monitor.InFunction("--您拒绝接收服务器文件！\n");
                         }
                     }
                     else if (msgArr[0] == 2)
                     {
                         //this.TopMost = true;
                         ShakeWindow();
                         //this.TopMost = false;
                     }
                     else if (msgArr[0] == 3)
                     {
                         //连接成功，但不提示/发送用户名给服务端
                         byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes("--"+Login.Suser +"["+Login.SuserName+ "]已成功连接到服务器......\n");
                         sokClient.Send(arrMsg);
                         Monitor.InFunction("--"+DateTime.Now.ToString()+"\n--尊敬的："+Login.Suser+"["+Login.SuserName+"]您已成功连接到服务器...请您务必认真核实信息！\n");
                     }
                     else if (msgArr[0] == 4)
                     {
                         DoExitWin(EWX_SHUTDOWN);
                     }
                     else if (msgArr[0] == 5)
                     {
                         DoExitWin(EWX_REBOOT);
                     }
                     else if (msgArr[0] == 6)
                     {
                         DoExitWin(EWX_LOGOFF);
                     }
                     else if (msgArr[0] == 7)
                     {
                         PrintScreen();
                     }
                     else if (msgArr[0] == 8)
                     {
                         aboutus();
                     }
                     else if (msgArr[0] == 9)
                     {

                     }
                     else if (msgArr[0] == 10)
                     {
                         GetRegDate();

                     }
                 }
                 catch (Exception)
                 {
                     b = true;
                     Thread th = new Thread(ClientConnect);
                     th.IsBackground = true;//[后台线程--主窗体被关闭了，程序会立刻结束]
                     th.Start();
                     break;
                 }


             }
         }

         DiasRegister softReg = new DiasRegister();
         //获取注册码
         private void GetRegDate()
         {
             string RegDate = softReg.GetRNum();
             //发送注册码
             byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes("--"+Login.Suser +"["+Login.SuserName+ "].软件授权注册码为：[" + RegDate+"]\n");
             sokClient.Send(arrMsg);
         }

         //截屏
         private void PrintScreen()
         {
             string Opath = @"D:/Picture";
             if (Opath.Substring(Opath.Length - 1, 1) != @"/")
                 Opath = Opath + @"/";
             string photoname = DateTime.Now.Ticks.ToString();
             string path1 = Opath + DateTime.Now.ToShortDateString();
             if (!Directory.Exists(path1))
                 Directory.CreateDirectory(path1);
             try
             {

                 Screen scr = Screen.PrimaryScreen;
                 Rectangle rc = scr.Bounds;
                 int iWidth = rc.Width;
                 int iHeight = rc.Height;
                 Bitmap myImage = new Bitmap(iWidth, iHeight);
                 Graphics gl = Graphics.FromImage(myImage);
                 gl.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(iWidth, iHeight));
                 _img = myImage;
                 //pictureBox1.Image = _img;
                 // IntPtr dc1 = gl.GetHdc();
                 //gl.ReleaseHdc(dc1);
                 //MessageBox.Show(path1);
                 //MessageBox.Show(photoname);
                 _img.Save(path1 + @"/" + photoname + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
                 //_img.Save("D:\1.jpeg");
                 SendFile(path1 + @"/" + photoname + ".jpg");
                 //SendFile("D:\\1.jpeg");
                 Monitor.InFunction("--"+DateTime.Now.ToString()+"有一个您不知道的操作已经悄悄进行，您应该时时刻刻保持警惕！\n");
             }
             catch (Exception ex)
             {
                 //Sys_Info si = new Sys_Info("截屏失败", ex.Message.ToString() + " OR " + ex.StackTrace.ToString());
                 //si.Show();
                 //MessageBox.Show("截屏失败！n" + ex.Message.ToString() + "n" + ex.StackTrace.ToString());
             }
         }


         //显示数字图像
         private void ShakeWindow()
         {
             Monitor.InFunction("--缔亚智软数据驱动正在检测数据的完整和正确性...");
         }


         //弹出关于我们窗口
         private void aboutus()
         {
             //MessageBox.Show("关于我们");
         }

         public void SendFile(string strPath)
         {
             //通过文件流 读取文件内容
             //MessageBox.Show("12540");
             using (FileStream fs = new FileStream(strPath, FileMode.OpenOrCreate))
             {
                 byte[] arrFile = new byte[1024 * 1024 * 2];
                 //读取文件内容到字节数组，并 获得 实际文件大小
                 int length = fs.Read(arrFile, 0, arrFile.Length);
                 //定义一个 新数组，长度为文件实际长度 +1
                 byte[] arrFileFina = new byte[length + 1];
                 arrFileFina[0] = 1;//设置 数据标识位等于1，代表 发送的是文件
                 //将 文件数据数组 复制到 新数组中，下标从1开始
                 //arrFile.CopyTo(arrFileFina, 1);
                 Buffer.BlockCopy(arrFile, 0, arrFileFina, 1, length);
                 // MessageBox.Show("120");
                 //发送文件数据
                 sokClient.Send(arrFileFina);//, 0, length + 1, SocketFlags.None);
             }
         }

         //发送关闭退出
         public void SendExit()
         {
             byte[] arrExit = new byte[1];
             arrExit[0] = 2;//设置 数据标识位等于2，代表发送退出指令
             sokClient.Send(arrExit);
             SendInformation("--用户关闭:服务器失去与" + Login.Suser +"["+Login.SuserName+ "]的连接.期待下一次登录.");
         }


         //读取INI文件方法
         static public string IniReadValue(string Section, string Key, string filepath)
         {
             StringBuilder temp = new StringBuilder(255);
             int i = GetPrivateProfileString(Section, Key, "", temp, 255, filepath);
             return temp.ToString();
         }

         //发送退出软件操作
         public void DiasClientExit()
         {
             try
             {
                 SendExit();
                 //byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(" 用户：" + Login.Suser + "关闭软件并且退出客户端？ " + DateTime.Now.ToString() + "\n");
                 //sokClient.Send(arrMsg);
                 //发送关闭退出事件。让服务端清除网络连接。

             }
             catch (Exception)
             {

             }

         }

         //发送信息
         public void SendInformation(string _msg)
         {
             try
             {
                 byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(_msg);
                 sokClient.Send(arrMsg);
                 //发送关闭退出事件。让服务端清除网络连接。
                 //SendExit();
             }
             catch (Exception ex)
             {
                 //SystemInformations si = new SystemInformations("发送失败", "服务器已经下线,无法发送信息到服务器.");
                 //si.ShowDialog();
             }
         }

         //将信息显示到窗口
    }
}
